// # axios核心封装
import axios, {
    type AxiosInstance,
    type AxiosRequestConfig,
    type AxiosResponse,
    type AxiosError
  } from "axios";
import { type BaseResponse, type RequestConfig } from "@/types/request"
// @ts-ignore
import Cookies from "js-cookie";
  
class Request {
  
  private instance: AxiosInstance;

  constructor(config: RequestConfig) {
    this.instance = axios.create({
      baseURL: import.meta.env.VITE_APP_BASE_API,
      timeout: 10000,
      ...config
    });
    this.setupInterceptors();
  }

  // 泛型请求方法
  public async request<T = any>(config: RequestConfig): Promise<BaseResponse<T>> {
    try {
      const response = await this.instance.request<BaseResponse<T>>(config);
      return response.data;
    } catch (err) {
      return this.handleError(err as AxiosError<BaseResponse>);
    }
  }

  // 拦截器配置
  private setupInterceptors() {
    this.instance.interceptors.request.use(
      // @ts-ignore
      (config: AxiosRequestConfig) => {
        const token = Cookies.get("token");
        if (token) {
          (config.headers as Record<string, any>).Authorization = `Bearer ${token}`;
        }
        return config;
      },
      (error: AxiosError) => Promise.reject(error)
    );
  
    this.instance.interceptors.response.use(
      (response: AxiosResponse<BaseResponse>) => {
        if (response.data.code !== 200) {
          return Promise.reject(response.data);
        }
        return response;
      },
      (error: AxiosError<BaseResponse>) => {
        this.handleError(error);
        return Promise.reject(error);
      }
    );
  }

  // 统一错误处理
  private handleError(error: AxiosError<BaseResponse>): never {
    const statusMap: Record<number, string> = {
      401: "请重新登录!",
      403: "Access denied",
      404: "资源未找到!",
      500: "服务异常请联系管理员!"
    };
    const msg = error.response?.data?.message 
      || statusMap[error.response?.status || 500]
      || "位置错误!";
    throw new Error(msg);
  }
  
  // 快捷方法（带泛型）
  /**
   * 封装 GET 请求方法（带泛型类型安全）
   * @param url 请求路径（必填）
   * @param config 请求配置（可选），包含 headers、params 等 Axios 原生配置
   * @returns Promise<BaseResponse<T>> 包含泛型类型 T 的响应结构
   */
  public get<T = any>(
    url: string,
    config?: RequestConfig
  ): Promise<BaseResponse<T>> {
    return this.request<T>({ ...config, method: "GET", url });
  }
  
  /**
   * 封装 POST 请求方法（带泛型类型安全）
   * @param url 请求路径（必填）
   * @param data 请求体数据（可选）
   * @param config 请求配置（可选），包含 headers、timeout 等扩展配置
   * @returns Promise<BaseResponse<T>> 包含泛型类型 T 的响应结构
   */
  public post<T = any>(
    url: string,
    data?: any,
    config?: RequestConfig
  ): Promise<BaseResponse<T>> {
    return this.request<T>({ ...config, method: "POST", url, data })
  }


  public async upload<T = any>(
    url: string,
    files: File | File[],          // 支持单文件或多文件上传
    data?: Record<string, any>,    // 其他表单数据
    config?: RequestConfig  & { timeout?: number }, // 基础配置  新增timeout类型
    options?: {                    // 上传专用配置
      fieldName?: string,          // 文件字段名（默认file）
      multipleField?: boolean      // 多文件是否使用多个字段（默认同名追加）
    }
  ): Promise<BaseResponse<T>> {
    // 新增文件类型校验
    // const validateFile = (file: File) => {
    //   if (!(file instanceof Blob)) {
    //     throw new Error(`无效文件类型: ${file.name}`);
    //   }
    //   if (!file.type.startsWith('image/')) {
    //     throw new Error(`仅支持图片格式: ${file.name}`);
    //   }
    // };

    const formData = new FormData();// 创建FormData对象
    const fieldName = options?.fieldName || 'file';// 处理文件字段名称
    const isMultipleField = options?.multipleField || false;
  
    // 校验文件参数
    if (!files || (Array.isArray(files) && files.length === 0)) {
      throw new Error('上传文件不能为空');
    }
  
    const filesArray = Array.isArray(files) ? files : [files];// 处理文件列表（统一转为数组）
  
    // 添加文件到表单
    filesArray.forEach((file, index) => {
      const finalField = isMultipleField ? `${fieldName}[${index}]` : fieldName;
      formData.append(finalField, file, file.name);
    });
  
    // 添加其他表单数据
    if (data) {
      Object.entries(data).forEach(([key, value]) => {
        if (Array.isArray(value)) {
          value.forEach(v => formData.append(`${key}[]`, v));
        } else if (value instanceof Blob) {
          formData.append(key, value);
        } else {
          formData.append(key, String(value));
        }
      });
    }
  
    // 合并配置（重点处理Content-Type）
    const mergedConfig: RequestConfig = {
      ...config,
      timeout: config?.timeout || 300000, // 默认5分钟超时
      headers: {
        ...config?.headers,
        // 注意：使用FormData时不要设置Content-Type，浏览器会自动添加带boundary的格式
      },
      data: formData
    };
  
    // 调用已有的post方法
    //return this.post<T>(url, formData, mergedConfig);
    try {
      const response = await this.post<T>(url, formData, mergedConfig);
      return response;
    } catch (error) {
      // 统一错误格式
      return {
        code: 500,
        msg: error,
        data: null as T
      };
    }
  }

  public async uploadExcel<T = any>(
    url: string,
    files: File | File[],          // 支持单文件或多文件上传
    data?: Record<string, any>,    // 其他表单数据
    config?: RequestConfig  & { timeout?: number }, // 基础配置  新增timeout类型
    options?: {                    // 上传专用配置
      fieldName?: string,          // 文件字段名（默认file）
      multipleField?: boolean      // 多文件是否使用多个字段（默认同名追加）
    }
  ): Promise<BaseResponse<T>> {

    const formData = new FormData();// 创建FormData对象
    const fieldName = options?.fieldName || 'file';// 处理文件字段名称
    const isMultipleField = options?.multipleField || false;
  
    // 校验文件参数
    if (!files || (Array.isArray(files) && files.length === 0)) {
      throw new Error('上传文件不能为空');
    }
  
    const filesArray = Array.isArray(files) ? files : [files];// 处理文件列表（统一转为数组）
  
    // 添加文件到表单
    // filesArray.forEach((file, index) => {
    //   const finalField = isMultipleField ? `${fieldName}[${index}]` : fieldName;
    //   formData.append(finalField, file, file.name);
    // });

    filesArray.forEach((file, index) => {
      const fieldNames = ['excel_first', 'excel_second'];
      formData.append(fieldNames[index], file, file.name);
    });
  
    // 添加其他表单数据
    if (data) {
      Object.entries(data).forEach(([key, value]) => {
        if (Array.isArray(value)) {
          value.forEach(v => formData.append(`${key}[]`, v));
        } else if (value instanceof Blob) {
          formData.append(key, value);
        } else {
          formData.append(key, String(value));
        }
      });
    }
  
    // 合并配置（重点处理Content-Type）
    const mergedConfig: RequestConfig = {
      ...config,
      timeout: config?.timeout || 300000, // 默认5分钟超时
      headers: {
        ...config?.headers,
        // 注意：使用FormData时不要设置Content-Type，浏览器会自动添加带boundary的格式
      },
      data: formData
    };
  
    // 调用已有的post方法
    //return this.post<T>(url, formData, mergedConfig);
    try {
      const response = await this.post<T>(url, formData, mergedConfig);
      return response;
    } catch (error) {
      // 统一错误格式
      return {
        code: 500,
        msg: error,
        data: null as T
      };
    }
  }
  
  

}

export default new Request({})